package model

// by daoyi
import (
	"gorm.io/gorm"
	"simai_oa/tool"
	"time"
)

type Model struct {
	ID        uint64    `gorm:"column:id;primary_key;auto_increment;comment:主键" json:"id" form:"id"`                       // 主键
	CreatedAt time.Time `gorm:"column:created_at;type:datetime;not null;comment:创建时间" json:"created_at" form:"created_at"` // 创建时间
	UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;not null;comment:更新时间" json:"updated_at" form:"updated_at"` // 更新时间
	CreatedBy uint64    `gorm:"column:created_by;default:0;not null;comment:创建人" json:"created_by" form:"created_by"`      // 创建人
	UpdatedBy uint64    `gorm:"column:updated_by;default:0;not null;comment:更新人" json:"updated_by" form:"updated_by"`      // 更新人
}

// 菜单
type Menu struct {
	Model
	Status      uint8  `gorm:"column:status;type:tinyint(1);not null;comment:状态(1:启用 2:不启用)" json:"status" form:"status"`                          // 状态(1:启用 2:不启用)
	Memo        string `gorm:"column:memo;size:64;comment:备注" json:"memo" form:"memo"`                                                             // 备注
	ParentID    uint64 `gorm:"column:parent_id;not null;comment:父级ID" json:"parent_id" form:"parent_id"`                                           // 父级ID
	URL         string `gorm:"column:url;size:72;comment:菜单URL" json:"url" form:"url"`                                                             // 菜单URL
	Name        string `gorm:"column:name;size:32;not null;comment:菜单名称" json:"name" form:"name"`                                                  // 菜单名称
	Sequence    int    `gorm:"column:sequence;not null;comment:排序值" json:"sequence" form:"sequence"`                                               // 排序值
	MenuType    uint8  `gorm:"column:menu_type;type:tinyint(1);not null;comment:菜单类型 1模块2菜单3操作" json:"menu_type" form:"menu_type"`                 // 菜单类型 1模块2菜单3操作
	Code        string `gorm:"column:code;size:32;not null;unique_index:uk_menu_code;comment:菜单代码" json:"code" form:"code"`                        // 菜单代码
	Icon        string `gorm:"column:icon;size:32;comment:icon" json:"icon" form:"icon"`                                                           // icon
	OperateType string `gorm:"column:operate_type;size:32;not null;comment:操作类型 none/add/del/view/update" json:"operate_type" form:"operate_type"` // 操作类型 none/add/del/view/update
	Menu        []Menu `gorm:"foreignKey:parent_id" json:"menu"`
}

// 添加前
func (m *Menu) BeforeCreate(tx *gorm.DB) error {
	m.CreatedAt = time.Now()
	m.UpdatedAt = time.Now()
	return nil
}

// 更新前
func (m *Menu) BeforeUpdate(tx *gorm.DB) error {
	m.UpdatedAt = time.Now()
	return nil
}

// 获取菜单有权限的操作列表
func (Menu) GetMenuButton(adminsid uint64, menuCode string, btns *[]string) (err error) {
	sql := `select operate_type from za_menu
	      where id in (
					select menu_id from za_role_menu where 
					menu_id in (select id from za_menu where parent_id in (select id from za_menu where code=?))
					and role_id in (select role_id from za_admin where id=?)
				)`
	err = tool.Gdb.Raw(sql, menuCode, adminsid).Pluck("operate_type", btns).Error
	return
}

// 获取管理员权限下所有菜单
func (Menu) GetMenuByAdminsid(adminsid uint64, menus *[]Menu) (err error) {
	sql := `select * from za_menu
	      where id in (
					select menu_id from za_role_menu where 
				  role_id in (select role_id from za_admin where id=?)
				)`
	err = tool.Gdb.Raw(sql, adminsid).Find(menus).Error
	return
}

// 删除菜单及关联数据
func (Menu) Delete(menuids []uint64) error {
	tx := tool.Gdb.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		tx.Rollback()
		return err
	}
	for _, menuid := range menuids {
		if err := deleteMenuRecurve(tx, menuid); err != nil {
			tx.Rollback()
			return err
		}
	}
	if err := tx.Where("menu_id in (?)", menuids).Delete(&RoleMenu{}).Error; err != nil {
		tx.Rollback()
		return err
	}
	if err := tx.Where("id in (?)", menuids).Delete(&Menu{}).Error; err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit().Error
}

func deleteMenuRecurve(db *gorm.DB, parentID uint64) error {
	where := &Menu{}
	where.ParentID = parentID
	var menus []Menu
	dbslect := db.Where(&where)
	if err := dbslect.Find(&menus).Error; err != nil {
		return err
	}
	for _, menu := range menus {
		if err := db.Where("menu_id = ?", menu.ID).Delete(&RoleMenu{}).Error; err != nil {
			return err
		}
		if err := deleteMenuRecurve(db, menu.ID); err != nil {
			return err
		}
	}
	if err := dbslect.Delete(&Menu{}).Error; err != nil {
		return err
	}
	return nil
}
